#include <sparrow/http_header_variant_set.h>
#include <sparrow/variant_headers.h>
#include <sparrow/errors.h>
#include <sparrow/util.h>

HttpHeaderVariantSet ::HttpHeaderVariantSet()
    :   header_(new VariantSet),
        headers_(new VariantSet)
{
    header_->set("headers", headers_);
}

HttpHeaderVariantSet ::~HttpHeaderVariantSet ()
{
    delete header_;
}

void HttpHeaderVariantSet::method(const Slice &method)
{
    header_->set("method", new VariantString(method.begin(), method.end()));
}

void HttpHeaderVariantSet::request_uri(const Slice &uri,
                           const Slice &schema,
                           const Slice &user_info,
                           const Slice &host,
                           int port,
                           const Slice &path,
                           const Slice &query,
                           const Slice &fragment)
{
    VariantSet *urivar = new VariantSet;
    header_->set("request-uri", urivar);

    urivar->set("request-uri", new VariantString(uri.begin(), uri.end()));
    urivar->set("schema", new VariantString(schema.begin(), schema.end()));
    urivar->set("user-info", new VariantString(user_info.begin(), user_info.end()));
    urivar->set("host", new VariantString(host.begin(), host.end()));
    urivar->set("port", new VariantInt32(port));
    urivar->set("path", new VariantString(path.begin(), path.end()));
    urivar->set("query", new VariantString(query.begin(), query.end()));
    urivar->set("fragment", new VariantString(fragment.begin(), fragment.end()));
}

void HttpHeaderVariantSet::version(const Slice &version, int major, int minor)
{
    header_->set("version", new VariantString(version.begin(), version.end()));
    header_->set("version-major", new VariantInt32(major));
    header_->set("version-minor", new VariantInt32(minor));
}


void HttpHeaderVariantSet::status(int code, const Slice &reason)
{
    header_->set("status", new VariantInt32(code));
    header_->set("reason", new VariantString(reason.begin(), reason.end()));
}

void HttpHeaderVariantSet::header(const Slice &header, const Slice &name, const Slice &value)
{
    VariantSet *h = new VariantSet;
    headers_->insert(h);
    h->set("header", new VariantString(header.begin(), header.end()));
    h->set("name", new VariantString(name.begin(), name.end()));
    h->set("value", new VariantString(value.begin(), value.end()));
}

void HttpHeaderVariantSet::reset()
{
    delete header_;
    headers_ = new VariantSet;
    header_ = new VariantSet;
    header_->insert(headers_);
}

VariantSet *HttpHeaderVariantSet::release_header()
{
    VariantSet *h = header_;
    header_ = NULL;
    headers_ = NULL;
    return h;
}

const std::string *HttpHeaderVariantSet::header(const std::string &name, const std::nothrow_t &) const
{
    if(header_ == NULL)
    {
        return NULL;
    }

    if(headers_ == NULL)
    {
        return NULL;
    }

    for(int i = 0; i < headers_->array_size(); ++i)
    {
        Variant *tmp = headers_->get(i, std::nothrow);
        if(tmp != NULL)
        {
            VariantSet *h = tmp->variant_set();
            Variant *header_name = h->get("name");
            if(header_name != NULL)
            {
                if(equal_no_case(header_name->str(), name))
                {
                    Variant *header_value = h->get("value", std::nothrow);
                    if(header_value != NULL)
                    {
                        return &header_value->str();
                    }
                }
            }
        }
    }
    return NULL;
}

const std::string *HttpHeaderVariantSet::header(const std::string &name) const
{
    const std::string *value = header(name, std::nothrow);
    if(value == NULL)
    {
        throw_error<std::runtime_error>(__FILE__, __LINE__,
                "prevent NULL pointer access");
    }
    return value;
}

